# Copyright (C) 2007 Laszlo Pandy <laszlok2@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import gtk
import pango
import datetime
Date = datetime.date
import decimal
Dec = decimal.Decimal

from AdventureMoney.core import Utils
import InterfaceUtils

class MoneyOwedView(gtk.Frame):
	
	#STYLE_NORM = (pango.WEIGHT_NORMAL, pango.STYLE_NORMAL)
	STYLE = (pango.WEIGHT_BOLD, pango.STYLE_NORMAL)
	
	def __init__(self, account):
		gtk.Frame.__init__(self)
		self.wTree = InterfaceUtils.GetGladeTree("MoneyOwedViewHolder")
		
		signals = {
			"OnMonthChanged"  : self.OnComboChanged,
			"OnYearChanged"   : self.OnComboChanged
		}
		self.wTree.signal_autoconnect(signals)
		
		self.account = account
		self.account.connect("people", self.UpdateInterface)
		self.account.connect("manager", self.UpdateInterface)
		self.account.connect("bills", self.UpdateInterface)
		
		self.updating = False
		
		self.vbox = self.wTree.get_widget("MoneyOwedViewVBox")
		self.wTree.get_widget("MoneyOwedViewHolder").remove(self.vbox)
		self.add(self.vbox)
		
		self.treeview = self.wTree.get_widget("MoneyOwedTreeView")
		types = (str,) * 5 + (pango.Weight, pango.Style)
		self.model = gtk.ListStore(*types)
		self.treeview.set_model(self.model)
		
		insCol = self.treeview.insert_column_with_attributes
		Cell = gtk.CellRendererText
		insCol(-1, "Name", 		Cell(), text=0)
		insCol(-1, "Previous Balance",	Cell(), text=1)
		insCol(-1, "Paid This Month", 	Cell(), text=2)
		insCol(-1, "Shared This Month", Cell(), text=3)
		insCol(-1, "Owes", 		Cell(), text=4, weight=5, style=6)
		
		self.monthCombo = self.wTree.get_widget("MonthComboBox")
		
		self.yearCombo = self.wTree.get_widget("YearComboBox")
		self.yearModel = gtk.ListStore(str)
		self.yearCombo.set_model(self.yearModel)
		self.yearCombo.set_column_span_column(0)
		
		self.managerOwedLabel = self.wTree.get_widget("ManagerOwedLabel")
		self.averageErrorLabel = self.wTree.get_widget("AverageErrorLabel")
		
		self.show_all()
	
	def OnComboChanged(self, widget):
		self.UpdateModel()
	
	@InterfaceUtils.UpdatingGUI
	def UpdateModel(self):
		self._UpdateModel()
		
	def _UpdateModel(self):
		zero = Dec(0)
		bLThisMonth = self.GetBillsForThisMonth()
		bLPreviousMonths = self.GetBillsForPreviousMonths()
		peopleDict = {}
		peopleSorted = []
		for person in self.account.getPeople():
			if self.account.isManager(person):
				continue
			# a tuple with balance, paid, shared and owed
			peopleDict[person]  = [None, None, None, None]
			peopleSorted.append(person)
		
		paidDict = bLPreviousMonths.totalPeoplePaid()
		sharedDict = bLPreviousMonths.totalPeopleShared()
		paidThisMonthDict = bLThisMonth.totalPeoplePaid()
		sharedThisMonthDict = bLThisMonth.totalPeopleShared()
		for person, valuesList in peopleDict.iteritems():
			paid = paidDict.get(person, zero)
			shared = sharedDict.get(person, zero)
			valuesList[0] = "%.2f" % (shared - paid)
			
			paidThisMonth = paidThisMonthDict.get(person, zero)
			valuesList[1] = "%.2f" % paidThisMonth
			
			sharedThisMonth = sharedThisMonthDict.get(person, zero)
			valuesList[2] = "%.2f" % sharedThisMonth
			
			# the total owing is simply the total shared in this month AND all previous months
			# minus the total paid in this month AND all previous months
			paid += paidThisMonth
			shared += sharedThisMonth
			value = (shared - paid)
			#remove any -0.00 strings
			if value == 0:
				value = zero
			valuesList[3] = "%.2f" % value
		
		self.model.clear()
		for person in peopleSorted:
			(bal, paid, share, owed) = peopleDict[person]
			t = (str(person), bal, paid, share, owed) + self.STYLE
			self.model.append(t)
			
		manager = self.account.getManager()
		if manager:
			paid = paidDict.get(manager, zero)
			paid += paidThisMonthDict.get(manager, zero)
			shared = sharedDict.get(manager, zero)
			shared += sharedThisMonthDict.get(manager, zero)
			managerOwed = (shared - paid)
			#round error to two decimal places
			error = Dec("%.2f" % managerOwed)
			
			message = "%s is owed <b>%.2f</b> this month"
			#don't allow negative zero
			if managerOwed == 0:
				# this will remove any negative sign from in front of the zero
				managerOwed == Dec(0)
			else:
				# switch the sign so it matches the message "... is owed $10..."
				managerOwed *= -1
			self.managerOwedLabel.set_markup(message % (manager.getName(), managerOwed))
			
			
			for person, (bal, paid, share, owed) in peopleDict.iteritems():
				#round error to two decimal places
				calc = Dec(owed)
				error += calc
		
			self.averageErrorLabel.set_markup("Total error is <b>%.3f</b>" % abs(error))
	
	@InterfaceUtils.UpdatingGUI
	def UpdateInterface(self, widget=None):
		today = Date.today()
		
		monthIndex = self.monthCombo.get_active()
		if monthIndex == -1:
			monthIndex = today.month -1
		self.monthCombo.set_active(max(0, monthIndex))
		
		yearIndex = self.yearCombo.get_active()
		self.yearModel.clear()
		yearList = self.account.getBills().getYearList()
		
		if not today.year in yearList:
			yearList.append(today.year)
		yearList.sort()
		for year in yearList:
			self.yearModel.append( (str(year),) )
		
		if not 0 <= yearIndex < len(self.yearModel):
			yearIndex = yearList.index(today.year)
		self.yearCombo.set_active(yearIndex)
		
		self._UpdateModel()
	
	def GetBillsForThisMonth(self):
		billsList = self.account.getBills()
		month = self.GetSelectedMonth()
		year = self.GetSelectedYear()
		billsList.filterByYearAndMonth(year, month)
		return billsList
	
	def GetBillsForPreviousMonths(self):
		billsList = self.account.getBills()
		lower = Date.min
		upper = Date(self.GetSelectedYear(), self.GetSelectedMonth(), 1)
		upper = upper - datetime.timedelta(days=1)
		billsList.filterByDate(lower, upper)
		
		return billsList
	
	def GetSelectedYear(self):
		yearIter = self.yearCombo.get_active_iter()
		year = self.yearModel.get_value(yearIter, 0)
		return int(year)
		
	def GetSelectedMonth(self):
		return self.monthCombo.get_active() + 1
		
